#include"martix.h"
#include"QDebug"
martix::martix(fraction* b, int r, int l) {
	int num = 0;
	m = r;
	n = l;
	element = new fraction * [m];
	for (int i = 0; i < m; i++)
		element[i] = new fraction[n];
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			element[i][j] = b[num++];
};
martix::martix(int r, int l) {
	m = r;
	n = l;
	element = new fraction * [m];
	for (int i = 0; i < m; i++)
		element[i] = new fraction[n];
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			element[i][j] = 0;
}
martix martix::operator + (martix& b) {
	martix a(m, n);
	if (m == b.m && n == b.n)
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a.element[i][j] = element[i][j] + b.element[i][j];
	else
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a.element[i][j] = ERROR_CODE;
	return a;
};
martix martix::operator - (martix& b) {
	martix a(m, n);
	if (m == b.m && n == b.n)
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a.element[i][j] = element[i][j] - b.element[i][j];
	else
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a.element[i][j] = ERROR_CODE;
	return a;
};
martix martix::operator * (martix& b) {
	martix a(m, b.n);
	if (n == b.m)
		for (int i = 0; i < m; i++)
			for (int j = 0; j < b.n; j++)
				for (int k = 0; k < n; k++) {
					fraction c = element[i][k] * b.element[k][j];
					a.element[i][j] = a.element[i][j] + c;
				}
	else
		for (int i = 0; i < m; i++)
			for (int j = 0; j < b.n; j++)
				a.element[i][j] = ERROR_CODE;
	return a;

};
fraction martix::det(){
    fraction a = 1;
    martix b(m,n);
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            b.element[i][j]=element[i][j];
if (m == n) {
		fraction value = 1;
		for (int k = 0; k < m; k++) {
            a=1;
			int l = -1;
			for (int i = k; i < n; i++)
                if (b.element[i][k] == a) {
					l = i;
					break;
				}
            if (l != -1){
                if(l!=k){
				for (int i = 0; i < m; i++)
                    swap(b.element[k][i], b.element[l][i]);
                value=-1*value;
                }
            }
            else {
				a = 0;
                for (int i = k; i < m; i++)
                    if (!(b.element[i][k] == a)) {
						l = i;
						break;
					}
				if (l == -1)
					return 0;
				else {
                    if(l!=k){
                    for (int i = 0; i < n; i++)
                        swap(b.element[k][i], b.element[l][i]);
                    value=-1*value;
                    }
                    value = value * b.element[k][k];
                    fraction temp=b.element[k][k];
					for (int j = 0; j < n; j++)
                        b.element[k][j] = b.element[k][j] / temp;
                }
            }
					for (int i = 0; i < m; i++)
						if (i != k) {
                            fraction temp = b.element[i][k];
                            for (int j = 0; j < n; j++) {
                                fraction tmp = temp * b.element[k][j];
                                b.element[i][j] = b.element[i][j] - tmp;
							}
						}

		}
		return value;
	}
else
return ERROR_CODE;
};
martix martix::inv() {
	martix a(m, n);
    martix b(m,n);
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            b.element[i][j]=element[i][j];
fraction c = 0;
    if (det().getp()==ERROR_CODE || det() == c)
		for (int i = 0; i < m; i++)
			for (int j = 0; j < n; j++)
				a.element[i][j] = ERROR_CODE;
	else {
		for (int i = 0; i < m; i++)
			a.element[i][i] = 1;
        for (int k = 0; k < m; k++) {
            c=1;
            int l = -1;
            for (int i = k; i < n; i++)
                if (b.element[i][k] == c) {
                    l = i;
                    break;
                }
            if (l != -1){
                if(l!=k){
                for (int i = 0; i < m; i++){
                    swap(b.element[k][i], b.element[l][i]);
                    swap(a.element[k][i],a.element[l][i]);
                }
                }
            }
            else {
                c = 0;
                for (int i = k; i < n; i++)
                    if (!(b.element[i][k] == c)) {
                        l = i;
                        break;
                    }
                for (int i = 0; i < m; i++){
                        swap(b.element[k][i], b.element[l][i]);
                        swap(a.element[k][i],a.element[l][i]);
                    }
                    fraction temp=b.element[k][k];
                    for (int j = 0; j < n; j++){
                        b.element[k][j] = b.element[k][j] / temp;
                        a.element[k][j] = a.element[k][j] / temp;
                    }

                            }

        for (int i = 0; i < m; i++)
            if (i != k) {
                fraction temp = b.element[i][k];
                for (int j = 0; j < n; j++) {
                    fraction tmp = temp * b.element[k][j];
                    b.element[i][j] = b.element[i][j] - tmp;
                    tmp=temp*a.element[k][j];
                    a.element[i][j] = a.element[i][j] - tmp;
                }
            }
        }
    }
	return a;
};

QString martix::print(){
    QString t="";
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
            if(element[i][j].getp()==ERROR_CODE)
            {
                t="计算不合法！";
                        return t;
            }
            t+=element[i][j].print()+"  ";
            if(j==n-1 && i!=m-1)
                t+="\n";
		}
	}
    return t;
};
martix operator * (int a, martix& b) {
	martix c(b.m, b.n);
	for (int i = 0; i < b.m; i++)
		for (int j = 0; j < b.n; j++)
			c.element[i][j] = a * b.element[i][j];
	return c;
};
martix operator * (martix& b, int a) {
	martix c(b.m, b.n);
	for (int i = 0; i < b.m; i++)
		for (int j = 0; j < b.n; j++)
			c.element[i][j] = a * b.element[i][j];
	return c;
};
martix operator * (fraction a, martix& b) {
	martix c(b.m, b.n);
	for (int i = 0; i < b.m; i++)
		for (int j = 0; j < b.n; j++)
			c.element[i][j] = a * b.element[i][j];
	return c;
};
martix operator * (martix& b, fraction a) {
	martix c(b.m, b.n);
	for (int i = 0; i < b.m; i++)
		for (int j = 0; j < b.n; j++)
			c.element[i][j] = a * b.element[i][j];
	return c;
};
